package com.xingda.packing.dmss.minitor.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xingda.packing.dmss.common.BaseEntity;
import com.xingda.packing.dmss.common.PackUtils;
import com.xingda.packing.dmss.config.appset.AppSetParam;
import com.xingda.packing.dmss.enums.EQType;
import com.xingda.packing.dmss.minitor.dto.PkBoxLayerDto;
import com.xingda.packing.dmss.minitor.dto.PkBoxLocationDto;
import com.xingda.packing.dmss.minitor.dto.PkTaskBoxDemandDto;
import com.xingda.packing.dmss.minitor.dto.PkWheelLocationDto;
import com.xingda.packing.dmss.minitor.entity.*;
import com.xingda.packing.dmss.minitor.mapper.PkBoxLocationMapper;
import com.xingda.packing.dmss.minitor.mapper.PkTaskDemandMapper;
import com.xingda.packing.dmss.minitor.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author anxiaoning
 * @since 2021-07-03
 */
@Service
public class PkBoxLocationServiceImpl extends ServiceImpl<PkBoxLocationMapper, PkBoxLocation>
        implements IPkBoxLocationService {

    @Resource
    private IPkTaskService pkTaskService;

    @Resource
    private PkBoxLocationMapper pkBoxLocationMapper;

    @Resource
    private IPkWheelService pkWheelService;

    @Resource
    private IPkTaskInfoService pkTaskInfoService;

    @Resource
    private IPkBoxLocationRealtionService pkBoxLocationRealtionService;

    @Resource
    private PkTaskDemandMapper pkTaskDemandMapper;

    @Override
    public List<PkBoxLocationDto> getPkBoxLocationList(int locationId, int area) {

        List<PkBoxLocationDto> dtos = new ArrayList<>();

        List<PkBoxLocation> locationList;

        LambdaQueryWrapper<PkBoxLocation> pkBoxLocationLambdaQueryWrapper = Wrappers.lambdaQuery();
        if (locationId > 0) {
            pkBoxLocationLambdaQueryWrapper.eq(PkBoxLocation::getId, locationId);
        }
        pkBoxLocationLambdaQueryWrapper.orderByAsc(PkBoxLocation::getBoxLocationNo);
        if (area == 1) {
            pkBoxLocationLambdaQueryWrapper.between(PkBoxLocation::getId, 1, 6);
        } else {
            pkBoxLocationLambdaQueryWrapper.between(PkBoxLocation::getId, 7, 12);

        }
        locationList = baseMapper.selectList(pkBoxLocationLambdaQueryWrapper);

        if (Objects.isNull(locationList) || locationList.isEmpty()) {
            return dtos;
        }
        // 关联
        List<PkBoxLocationRealtion> realtionList;
        if (area == 1) {
            realtionList = this.pkBoxLocationRealtionService.lambdaQuery()
                    .between(PkBoxLocationRealtion::getBoxLocationId, 1, 6).list();
        } else {
            realtionList = this.pkBoxLocationRealtionService.lambdaQuery()
                    .between(PkBoxLocationRealtion::getBoxLocationId, 7, 12).list();
        }
        List<Integer> licationIds = new ArrayList<>();
        locationList.forEach(l -> {
            PkBoxLocationDto dto = new PkBoxLocationDto();
            BeanUtils.copyProperties(l, dto);
            PkBoxLocationRealtion realtion = realtionList.stream()
                    .filter(r -> r != null && r.getBoxLocationId().compareTo(l.getId()) == 0).findAny().orElse(null);
            dto.setTaskId(realtion == null ? null : realtion.getTaskId());
            dtos.add(dto);
            licationIds.add(l.getId());
        });

        // 任务列表
        List<PkTask> tasks = this.pkTaskService.getPkTaskListByLocationIds(licationIds);
        if (tasks.size() == 0) {
            return dtos;
        }
        List<Integer> taskIds = tasks.stream().map(BaseEntity::getId).collect(Collectors.toList());
        dtos.forEach(dto -> {
            if (dto.getTaskId() != null) {
                PkTask task = tasks.stream().filter(t -> dto.getTaskId() != null && t.getId() == dto.getTaskId())
                        .findAny().orElse(null);

                PkTaskBoxDemandDto pkTaskBoxDemandDto = getByTaskId(dto.getTaskId());

                assert task != null;
                task.setBoxDescription(null);
                dto.setTask(task);
                dto.setBoxDemand(pkTaskBoxDemandDto);

                List<PkBoxLayerDto> pkBoxLayerDtos = new ArrayList<>();
                for (int i = 1; i <= dto.getTask().getLayer(); i++) {
                    PkBoxLayerDto pkBoxLayerDto = new PkBoxLayerDto();
                    pkBoxLayerDto.setLayer(i);
                    pkBoxLayerDto.setWheeLocationlList(new ArrayList<>());
                    pkBoxLayerDtos.add(pkBoxLayerDto);
                }
                dto.setLayerList(pkBoxLayerDtos);
            }
        });

        // 层列表
        List<Map<String, Object>> layerList = this.pkBoxLocationMapper.getPkBoxLayerList(taskIds);

        // 关联表集合
        List<PkTaskInfo> taskInfoList = this.pkTaskInfoService.lambdaQuery().in(PkTaskInfo::getTaskId, taskIds)
                .orderByAsc(PkTaskInfo::getPostion).orderByAsc(PkTaskInfo::getPutTime).list();
        List<PkWheel> wheelList = this.pkWheelService.getPkWheelByPutTime(taskIds);

        dtos.forEach(dto -> {
            if (dto.getTaskId() == null) {
                return;
            }

            if (dto.getTask() == null) {// 未绑定任务,跳过
                return;
            }
            // 已装轮数
            int totalWheelCount = 0;
            // 焊点总数
            int totalSolderCount = 0;

            for (int i = 1; i <= dto.getTask().getLayer(); i++) {

                PkBoxLayerDto layerDto = dto.getLayerList().get(i - 1);
                layerDto.setLayer(i);
                Map<String, Object> map = null;

                int finalI = i;
                if (Objects.nonNull(layerList) && !layerList.isEmpty()) {
                    map = layerList.stream()
                            .filter(m -> Integer.parseInt(m.get("layer").toString()) == finalI
                                    && Integer.parseInt(m.get("taskId").toString()) == dto.getTask().getId())
                            .findAny().orElse(null);
                }
                if (map != null) {// 填充
                    int solderCount = Integer.parseInt(map.get("solder").toString());
                    layerDto.setSolder(solderCount);
                    layerDto.setTorqueValue(Double.parseDouble(map.get("torqueValue").toString()));
                    int wheelCount = Integer.parseInt(map.get("wheelCount").toString());

                    int solderJointWheelCount = 0;
                    Object solderJointWheelCountObject = map.get("solderJointWheelCount");
                    if (Objects.nonNull(solderJointWheelCountObject)) {
                        solderJointWheelCount = Integer.parseInt(map.get("solderJointWheelCount").toString());
                    }
                    layerDto.setSolderJointWheelCount(solderJointWheelCount);
                    layerDto.setState(wheelCount - (dto.getTask().getBoxWheelSum() / dto.getTask().getLayer()) == 0 ? 3 : 2);
                    layerDto.setStrandDeviation(Double.parseDouble(map.get("strandDeviation").toString()));

                    totalWheelCount += wheelCount;
                    totalSolderCount += solderCount;
                } else {
                    layerDto.setState(1);
                }
                List<Integer> subIds = taskInfoList.stream()
                        .filter(ti -> ti.getTaskId().compareTo(dto.getTask().getId()) == 0
                                && ti.getLayer().compareTo(finalI) == 0)
                        .map(PkTaskInfo::getWheelId).collect(Collectors.toList());
                List<PkWheel> subList = wheelList.stream().filter(pkWheel -> subIds.contains(pkWheel.getId()))
                        .collect(Collectors.toList());

                int floorCount = dto.getTask().getFloorCount();
                List<PkWheelLocationDto> wheeLocationlList = toPkWheelLocationDtos(subList, floorCount);
                long anewWheelCount = wheeLocationlList.stream()
                        .map(PkWheelLocationDto::getPkWheel)
                        .filter(Objects::nonNull)
                        .filter(wheel -> EQType.ANEW.getType().equalsIgnoreCase(wheel.getEqType())).count();
                layerDto.setAnewWheelCount((int) anewWheelCount);
                layerDto.setWheeLocationlList(wheeLocationlList);
                dto.getLayerList().set(i - 1, layerDto);
            }
            dto.setSolderCount(totalSolderCount);
            dto.setWheelCount(totalWheelCount);
        });

        return dtos;
    }

    /**
     * 获得工字轮信息和工字轮位置信息集合
     *
     * @param subList    当前每层工字轮集合
     * @param floorCount 每层要求装箱数量(小于等于12个)
     */
    private List<PkWheelLocationDto> toPkWheelLocationDtos(List<PkWheel> subList, int floorCount) {
        List<PkWheelLocationDto> wheeLocationlList = new ArrayList<>();
        for (int j = 0; j < floorCount; j++) {
            wheeLocationlList.add(null);
        }
        List<Integer> sortList = AppSetParam.wheel_sort_index;
        int subSize = (Objects.nonNull(subList) && !subList.isEmpty()) ? subList.size() : 0;

        for (int j = 0; j < floorCount; j++) {
            PkWheelLocationDto pkWheelLocationDto = new PkWheelLocationDto();
            int sortIndex = sortList.get(j);
            PkWheel wheel = subSize - 1 >= j ? subList.get(j) : null;
            pkWheelLocationDto.setPkWheel(wheel);
            pkWheelLocationDto.setLocationNo(j + 1);
            pkWheelLocationDto.setLocationNo2(changeSort(pkWheelLocationDto.getLocationNo()));
            wheeLocationlList.set(sortIndex, pkWheelLocationDto);
        }
        return wheeLocationlList;
    }

    private Integer changeSort(Integer locationNo) {
//        12 1
//        11 8
//        10 9
//        5 2
//        1 7
//        3 10
//        6 3
//        2 6
//        4 11
//        8 4
//        7 5
//        9 12
        if (locationNo == 12) {
            return 1;
        } else if (locationNo == 11) {
            return 8;
        } else if (locationNo == 10) {
            return 9;
        } else if (locationNo == 5) {
            return 2;
        } else if (locationNo == 1) {
            return 7;
        } else if (locationNo == 3) {
            return 10;
        } else if (locationNo == 6) {
            return 3;
        } else if (locationNo == 2) {
            return 6;
        } else if (locationNo == 4) {
            return 11;
        } else if (locationNo == 8) {
            return 4;
        } else if (locationNo == 7) {
            return 5;
        }
        return 12;
    }

    private PkTaskBoxDemandDto getByTaskId(Integer taskId) {
        PkTaskBoxDemandDto pkTaskBoxDemandDto = null;
        if (Objects.nonNull(taskId)) {
            LambdaQueryWrapper<PkTaskDemand> pkTaskDemandLambdaQueryWrapper = Wrappers.lambdaQuery();
            pkTaskDemandLambdaQueryWrapper.eq(PkTaskDemand::getTaskId, taskId).orderByAsc(PkTaskDemand::getSortIndex);
            List<PkTaskDemand> pkTaskDemands = pkTaskDemandMapper.selectList(pkTaskDemandLambdaQueryWrapper);
            if (Objects.nonNull(pkTaskDemands) && !pkTaskDemands.isEmpty()) {
                pkTaskBoxDemandDto = PackUtils.toPkTaskBoxDemandDto(pkTaskDemands);
            }
        }
        return pkTaskBoxDemandDto;
    }

}
